package net.mgsx.product.t2m.modisco.testability;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import net.mgsx.product.t2m.modisco.tools.ModiscoUtils;

import org.eclipse.gmt.modisco.java.AbstractMethodInvocation;
import org.eclipse.gmt.modisco.java.AbstractTypeDeclaration;
import org.eclipse.gmt.modisco.java.ClassDeclaration;
import org.eclipse.gmt.modisco.java.FieldDeclaration;
import org.eclipse.gmt.modisco.java.InterfaceDeclaration;
import org.eclipse.gmt.modisco.java.Type;

public class MockAnalysis {

	private Collection<AbstractTypeDeclaration> mockableDependencies;
	
	private Collection<AbstractTypeDeclaration> unmockableDependencies;
	
	public void analyse(final ClassDeclaration context)
	{
		mockableDependencies = new HashSet<AbstractTypeDeclaration>();
		unmockableDependencies = new HashSet<AbstractTypeDeclaration>();
		
		// check all attributes
		
		for(FieldDeclaration field : ModiscoUtils.getElements(context, FieldDeclaration.class))
		{
			Type type = field.getType().getType();
			if(type instanceof InterfaceDeclaration)
			{
				mockableDependencies.add((InterfaceDeclaration)type);
			}
			else if(type instanceof ClassDeclaration)
			{
				if(type != context && !type.isProxy())
				{
					unmockableDependencies.add((ClassDeclaration)type);
				}
			}
			else
			{
				ModiscoUtils.getLogger().logWarning("unhandled type " + type.eClass().getName());
			}
		}
		
		for(AbstractMethodInvocation invocation : ModiscoUtils.getElements(context, AbstractMethodInvocation.class))
		{
			AbstractTypeDeclaration methodOwner = invocation.getMethod().getAbstractTypeDeclaration();
			
			if(methodOwner == null)
			{
				ModiscoUtils.getLogger().logWarning("null method owner");
			}
			else if(methodOwner instanceof InterfaceDeclaration)
			{
				mockableDependencies.add(methodOwner);
			}
			else if(methodOwner instanceof ClassDeclaration)
			{
				if(methodOwner != context)
				{
					unmockableDependencies.add(methodOwner);
				}
			}
			else
			{
				ModiscoUtils.getLogger().logWarning("unknown type " + methodOwner.eClass().getName());
			}
		}
	}

	/**
	 * @return the mockableDependencies
	 */
	public final Collection<AbstractTypeDeclaration> getMockableDependencies() {
		return mockableDependencies;
	}

	/**
	 * @return the unmockableDependencies
	 */
	public final Collection<AbstractTypeDeclaration> getUnmockableDependencies() {
		return unmockableDependencies;
	}
	
	
	
}
